lexer grammar CommonLexer;

options {
    language=CSharp;
}

@lexer::namespace {
    Common.Grammar.Antlr
}

///////////////////////////////////////////////////////////////////////////////
// operators
TOKEN_OP_LPARENT		: '('	;
TOKEN_OP_RPARENT		: ')'	;
TOKEN_OP_LBRACE         : '{'	;
TOKEN_OP_RBRACE         : '}'	;
TOKEN_OP_EQUALEQUAL		: '=='	;
TOKEN_OP_BANGEQ			: '!='	;
TOKEN_OP_GE				: '>='	;
TOKEN_OP_LE				: '<='	;
TOKEN_OP_OR				: '||'	;
TOKEN_OP_AND			: '&&'	;
TOKEN_OP_PLUS			: '+'	;
TOKEN_OP_DASH			: '-'	;
TOKEN_OP_STAR			: '*'	;
TOKEN_OP_CARET			: '^'	;
TOKEN_OP_SLASH			: '/'	;
TOKEN_OP_MODULUS		: '%'	;
TOKEN_OP_EQUAL			: '='	;
TOKEN_OP_GT				: '>'	;
TOKEN_OP_LT			    : '<'	;
TOKEN_OP_QUES			: '?'	;
TOKEN_OP_BANG			: '!'	;
TOKEN_OP_VERSUS			: '&'	;
TOKEN_OP_EITHER			: '|'	;
TOKEN_OP_COLON			: ':'	;
TOKEN_OP_COMMA			: ','	;

///////////////////////////////////////////////////////////////////////////////

TOKEN_KEY_TRUE
    :    T R U E
    ;

TOKEN_KEY_FALSE
    :    F A L S E
    ; 

TOKEN_KEY_NEW
    :   N E W
    ;
	
/////////////////////////////////////////////////////////////////////////////////////////   
TOKEN_IDENTIFIER
    :   (LETTER | UNDERSCORE) (LETTER | DIGIT | UNDERSCORE)*
    ;

BLANK
    :   WS+ -> channel(HIDDEN)
    ;

SL_COMMENT
    :   '//' ~[\r\n]* -> channel(HIDDEN)        //-> skip
    ;

ML_COMMENT
    :    '/*' (ML_COMMENT | ~([/*] | [*/]))* '*/' -> channel(HIDDEN)        //-> skip
    ;

TOKEN_CONST_STRING
    :   '"' ( ESC | ~('"' | [\r\n]))* '"'
    |   '\'' ( ESC | ~('\'' | [\r\n]))* '\''
    |   '\\"' ( ESC | ~([\r\n]))* '\\"'
    |   '\\\'' ( ESC | ~([\r\n]))* '\\\''
    ;

TOKEN_CONST_INTEGER
    :   INTEGER
    ;

TOKEN_CONST_FLOAT
    :   FLOAT
    ;

TOKEN_CONST_DECIMAL
    :   DECIMAL
    ;

TOKEN_CONST_DOUBLE
    :   DOUBLE
    ;

TOKEN_CONST_DATE
    :   DATE
    ;

TOKEN_CONST_TIME
    :   TIME
    ;

fragment
EscapeSequence
    :   '\\' [btnfr"'\\]
    |   '\\' ([0-3]? [0-7])? [0-7]
    |   '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit
    ;

fragment
CommonCharacter
    :   SimpleEscapeSequence
    |   HexEscapeSequence
    |   UnicodeEscapeSequence
    ;

fragment
SimpleEscapeSequence
    :   '\\\''
    |   '\\"'
    |   '\\\\'
    |   '\\0'
    |   '\\a'
    |   '\\b'
    |   '\\f'
    |   '\\n'
    |   '\\r'
    |   '\\t'
    |   '\\v'
    ;

fragment
HexEscapeSequence
    :   '\\x' HexDigit
    |   '\\x' HexDigit HexDigit
    |   '\\x' HexDigit HexDigit HexDigit
    |   '\\x' HexDigit HexDigit HexDigit HexDigit
    ;

fragment
UnicodeEscapeSequence
    :   '\\u' HexDigit HexDigit HexDigit HexDigit
    |   '\\U' HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit
    ;

fragment
HexDigits
    :   HexDigit ((HexDigit | '_')* HexDigit)?
    ;

fragment
HexDigit
    :   [0-9a-fA-F]
    ;

fragment
WS
    :   (' ' | '\t' | '\f')
    ;

fragment
NEWLINE
    :   ('\r')? '\n'
    ;

fragment
ESC
    :   ('\\') ~[\r\n]
    ;

fragment
EXP
    :   E ('+' | '-')? DIGIT+
    ;

fragment
DIGIT
    :   '0'..'9'
    ;

fragment
DECIMAL
    :   INTEGER ('.' INTEGER)? EXP? 'm'
    |   '.' INTEGER EXP? 'm'
    ;

fragment
DOUBLE
    :   INTEGER '.' INTEGER? EXP? ('d')?
    |   '.' INTEGER EXP? ('d')?
	|   INTEGER EXP ('d')?
    ;

fragment
FLOAT
    :   INTEGER ('.' INTEGER)? EXP? 'f'
    |   '.' INTEGER EXP? 'f'
    ;

fragment
INTEGER
    :   DIGIT+
    ;

fragment
TIME
    :    DIGIT DIGIT? ':' DIGIT DIGIT ':' DIGIT DIGIT ('.' DIGIT+)? ' '? ('AM' | 'PM')?
    ;  

fragment
DATE
    :   DIGIT DIGIT DIGIT DIGIT '-' (DIGIT)+  '-' (DIGIT)+ (' ' DIGIT DIGIT? ':' DIGIT DIGIT ':' DIGIT DIGIT ('.' DIGIT+)? ' '? ('AM' | 'PM')?)?
    |   (DIGIT)+ '/' (DIGIT)+ '/' DIGIT DIGIT DIGIT DIGIT (' ' DIGIT DIGIT? ':' DIGIT DIGIT ':' DIGIT DIGIT ('.' DIGIT+)? ' '? ('AM' | 'PM')?)?
	;

fragment
LETTER
    :    ANSI_L | UNICODE_L
    ;

fragment
ANSI_L
    :    ('a'..'z' | 'A'..'Z')
    ;

fragment
UNICODE_L
    :    '\u0041'..'\u005a'
    |    '\u0061'..'\u007a'
    |    '\u00c0'..'\u00d6'
    |    '\u00d8'..'\u00f6'
    |    '\u00f8'..'\u00ff'
    |    '\u0100'..'\u1fff'
    |    '\u2000'..'\u303f'        
    |    '\u3040'..'\u318f'
    |    '\u3300'..'\u337f'
    |    '\u3400'..'\u3d2d'
    |    '\u4e00'..'\u9fff'
    |    '\uac00'..'\ud7af'
    |    '\uf900'..'\ufaff'
    |    '\uff10'..'\uff19' // Support Japanese
    |    '\uff21'..'\uff3a'
    |    '\uff41'..'\uff5a'
    |    '\uff66'..'\uff9d'
    ;

fragment
UNDERSCORE
    :    '_'
    ;

///////////////////////////////////////////////////////////////////////////////
fragment A
    :    ('a' | 'A')
    ;

fragment B
    :    ('b' | 'B')
    ;

fragment C
    :    ('c' | 'C')
    ;

fragment D
    :    ('d' | 'D')
    ;

fragment E
    :    ('e' | 'E')
    ;

fragment F
    :    ('f' | 'F')
    ;

fragment G
    :    ('g' | 'G')
    ;

fragment H
    :    ('h' | 'H')
    ;

fragment I
    :    ('i' | 'I')
    ;

fragment J
    :    ('j' | 'J')
    ;

fragment K
    :    ('k' | 'K')
    ;

fragment L
    :    ('l' | 'L')
    ;

fragment M
    :    ('m' | 'M')
    ;

fragment N
    :    ('n' | 'N')
    ;

fragment O
    :    ('o' | 'O')
    ;

fragment P
    :    ('p' | 'P')
    ;

fragment Q
    :    ('q' | 'Q')
    ;

fragment R
    :    ('r' | 'R')
    ;

fragment S
    :    ('s' | 'S')
    ;

fragment T
    :    ('t' | 'T')
    ;

fragment U
    :    ('u' | 'U')
    ;

fragment V
    :    ('v' | 'V')
    ;

fragment W
    :    ('w' | 'W')
    ;

fragment X
    :    ('x' | 'X')
    ;

fragment Y
    :    ('y' | 'Y')
    ;

fragment Z
    :    ('z' | 'Z')
    ;
